<!DOCTYPE html>
<html>
<!--
Copyright The Closure Library Authors. All Rights Reserved.

Use of this source code is governed by the Apache License, Version 2.0.
See the COPYING file for details.
-->
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
  <title>Closure Performance Tests - goog.ui.Set vs goog.ui.StringSet</title>
  <link rel="stylesheet" type="text/css" href="../testing/performancetable.css"/>
  <script src="../base.js"></script>
  <script>
    goog.require('goog.functions');
    goog.require('goog.string');
    goog.require('goog.structs.Set');
    goog.require('goog.structs.StringSet');
    goog.require('goog.testing.PerformanceTable');
    goog.require('goog.testing.PropertyReplacer');
    goog.require('goog.testing.jsunit');
  </script>
</head>
<body>
  <h1>goog.ui.Set and goog.ui.StringSet Performance Tests</h1>
  <p>
    <strong>User-agent:</strong>
    <script>document.write(navigator.userAgent);</script>
  </p>
  <div id="perfTable"></div>
  <hr>

  <script>
    var table = new goog.testing.PerformanceTable(
        goog.dom.getElement('perfTable'));

    // Number of operations to measure in each table line.
    var OPS_COUNT = 100000;

    var stubs = new goog.testing.PropertyReplacer();

    function tearDown() {
      stubs.reset();
    }

    function testCreateSetFromArrayWithoutRepetition() {
      var values = []
      for (var i = 0; i < OPS_COUNT; i++) {
        values.push(i);
      }

      table.run(function() {
        var s = new goog.structs.StringSet(values);
      }, 'Create string set from number array without repetition');

      values = []
      for (var i = 0; i < OPS_COUNT; i++) {
        values.push(String(i));
      }

      table.run(function() {
        var s = new goog.structs.StringSet(values);
      }, 'Create string set from string array without repetition');
    }

    function testCreateSetWithoutRepetition() {
      table.run(function() {
        var s = new goog.structs.Set();
        for (var i = 0; i < OPS_COUNT; i++) {
          s.add(i);
        }
      }, 'Add elements to set without repetition');

      table.run(function() {
        var s = new goog.structs.StringSet();
        for (var i = 0; i < OPS_COUNT; i++) {
          s.add(i);
        }
      }, 'Add elements to string set without repetition');

      stubs.replace(goog.structs.StringSet, 'encode_', goog.functions.identity);
      stubs.replace(goog.structs.StringSet, 'decode_', goog.functions.identity);

      table.run(function() {
        var s = new goog.structs.StringSet();
        for (var i = 0; i < OPS_COUNT; i++) {
          s.add(i);
        }
      }, 'Add elements to string set without repetition and escaping');
    }

    function testCreateSetWithRepetition() {
      table.run(function() {
        var s = new goog.structs.Set();
        for (var n = 0; n < 10 ; n++) {
          for (var i = 0; i < OPS_COUNT / 10; i++) {
            s.add(i);
          }
        }
      }, 'Add elements to set with repetition');

      table.run(function() {
        var s = new goog.structs.StringSet();
        for (var n = 0; n < 10; n++) {
          for (var i = 0; i < OPS_COUNT / 10; i++) {
            s.add(i);
          }
        }
      }, 'Add elements to string set with repetition');
    }

    function testGetCount() {
      var bigSet = new goog.structs.Set;
      var bigStringSet = new goog.structs.StringSet;
      for (var i = 0; i < OPS_COUNT; i++) {
        bigSet.add(i);
        bigStringSet.add(i);
      }

      table.run(function() {
        bigSet.getCount();
      }, 'Count the number of elements in a set');

      table.run(function() {
        bigStringSet.getCount();
      }, 'Count the number of elements in a string set');
    }

    function testGetValues() {
      var bigSet = new goog.structs.Set;
      var bigStringSet = new goog.structs.StringSet;
      for (var i = 0; i < OPS_COUNT; i++) {
        bigSet.add(i);
        bigStringSet.add(i);
      }

      table.run(function() {
        bigSet.getValues();
      }, 'Convert a set to array');

      table.run(function() {
        bigStringSet.getValues();
      }, 'Convert a string set to array');
    }

    function testForEach() {
      var bigSet = new goog.structs.Set;
      var bigStringSet = new goog.structs.StringSet;
      for (var i = 0; i < OPS_COUNT; i++) {
        bigSet.add(i);
        bigStringSet.add(i);
      }

      table.run(function() {
        goog.structs.forEach(bigSet, goog.nullFunction);
      }, 'Iterate over set with forEach');

      table.run(function() {
        goog.structs.forEach(bigStringSet, goog.nullFunction);
      }, 'Iterate over string set with forEach');
    }

    function testForEachWithLargeKeys() {
      var bigSet = new goog.structs.Set;
      var bigStringSet = new goog.structs.StringSet;
      for (var i = 0; i < OPS_COUNT / 100; i++) {
        bigSet.add(goog.string.repeat(String(i), 1000));
        bigStringSet.add(goog.string.repeat(String(i), 1000));
      }

      table.run(function() {
        for (var i = 0; i < 100; i++) {
          goog.structs.forEach(bigSet, goog.nullFunction);
        }
      }, 'Iterate over set of large strings with forEach');

      table.run(function() {
        for (var i = 0; i < 100; i++) {
          goog.structs.forEach(bigStringSet, goog.nullFunction);
        }
      }, 'Iterate over string set of large strings with forEach');
    }

    function testAddRemove() {
      table.run(function() {
        var s = new goog.structs.Set();
        for (var i = 0; i < OPS_COUNT / 2; i++) {
          s.add(i);
        }
        for (var i = 0; i < OPS_COUNT / 2; i++) {
          s.remove(i);
        }
      }, 'Add then remove elements from set');

      table.run(function() {
        var s = new goog.structs.StringSet();
        for (var i = 0; i < OPS_COUNT / 2; i++) {
          s.add(i);
        }
        for (var i = 0; i < OPS_COUNT / 2; i++) {
          s.remove(i);
        }
      }, 'Add then remove elements from string set');
    }

    function testContains() {
      var bigSet = new goog.structs.Set;
      var bigStringSet = new goog.structs.StringSet;
      var arr = [];
      for (var i = 0; i < OPS_COUNT; i++) {
        bigSet.add(i);
        bigStringSet.add(i);
        arr.push(i);
      }

      table.run(function() {
        for (var i = 0; i < OPS_COUNT; i++) {
          bigSet.contains(i);
        }
      }, 'Membership check for each element of set');

      table.run(function() {
        for (var i = 0; i < OPS_COUNT; i++) {
          bigStringSet.contains(i);
        }
      }, 'Membership check for each element of string set with contains');

      table.run(function() {
        bigStringSet.containsArray(arr);
      }, 'Membership check for each element of string set with containsArray');

      stubs.replace(goog.structs.StringSet, 'encode_', goog.functions.identity);
      stubs.replace(goog.structs.StringSet, 'decode_', goog.functions.identity);

      table.run(function() {
        for (var i = 0; i < OPS_COUNT; i++) {
          bigStringSet.contains(i);
        }
      }, 'Membership check for each element of string set without escaping');
    }

    function testEquals() {
      table.run(function() {
        var s1 = new goog.structs.Set();
        var s2 = new goog.structs.Set();
        for (var i = 0; i < OPS_COUNT / 4; i++) {
          s1.add(i);
          s2.add(i);
        }
        s1.equals(s2);
      }, 'Create then compare two sets');

      table.run(function() {
        var s1 = new goog.structs.StringSet();
        var s2 = new goog.structs.StringSet();
        for (var i = 0; i < OPS_COUNT / 4; i++) {
          s1.add(i);
          s2.add(i);
        }
        s1.equals(s2);
      }, 'Create then compare two string sets');
    }
  </script>
</body>
</html>
